package com.king.juc.n8.threadpooldemo.threadpool;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.*;

/**
 * @author king
 * @date 2020/12/8 22:51
 */
public class ThreadPoolExecutorDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                // 核心线程数量(最多保留的线程数)
                10,
                // 最大线程数量
                10,
                // 生存时间-针对救急线程
                1000,
                // 时间单位-针对救急线程
                TimeUnit.MILLISECONDS,
                // 阻塞队列
                new BlockingQueue<Runnable>() {
                    @Override
                    public boolean add(Runnable runnable) {
                        return false;
                    }

                    @Override
                    public boolean offer(Runnable runnable) {
                        return false;
                    }

                    @Override
                    public void put(Runnable runnable) throws InterruptedException {

                    }

                    @Override
                    public boolean offer(Runnable runnable, long timeout, TimeUnit unit) throws InterruptedException {
                        return false;
                    }

                    @Override
                    public Runnable take() throws InterruptedException {
                        return null;
                    }

                    @Override
                    public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
                        return null;
                    }

                    @Override
                    public int remainingCapacity() {
                        return 0;
                    }

                    @Override
                    public boolean remove(Object o) {
                        return false;
                    }

                    @Override
                    public boolean contains(Object o) {
                        return false;
                    }

                    @Override
                    public int drainTo(Collection<? super Runnable> c) {
                        return 0;
                    }

                    @Override
                    public int drainTo(Collection<? super Runnable> c, int maxElements) {
                        return 0;
                    }

                    @Override
                    public Runnable remove() {
                        return null;
                    }

                    @Override
                    public Runnable poll() {
                        return null;
                    }

                    @Override
                    public Runnable element() {
                        return null;
                    }

                    @Override
                    public Runnable peek() {
                        return null;
                    }

                    @Override
                    public int size() {
                        return 0;
                    }

                    @Override
                    public boolean isEmpty() {
                        return false;
                    }

                    @Override
                    public Iterator<Runnable> iterator() {
                        return null;
                    }

                    @Override
                    public Object[] toArray() {
                        return new Object[0];
                    }

                    @Override
                    public <T> T[] toArray(T[] a) {
                        return null;
                    }

                    @Override
                    public boolean containsAll(Collection<?> c) {
                        return false;
                    }

                    @Override
                    public boolean addAll(Collection<? extends Runnable> c) {
                        return false;
                    }

                    @Override
                    public boolean removeAll(Collection<?> c) {
                        return false;
                    }

                    @Override
                    public boolean retainAll(Collection<?> c) {
                        return false;
                    }

                    @Override
                    public void clear() {

                    }
                },
                // 线程工厂-可以为线程创建时起名字
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return null;
                    }
                },
                /*
                    拒绝策略
                    AbortPolicy 让调用者抛出 RejectedExecutionException 异常, 这是默认策略
                    CallerRunsPolicy 让调用者运行任务
                    DiscardPolicy 放弃本次任务
                    DiscardOldestPolicy 放弃队列中最早的任务, 本任务取而代之
                    第三方
                    Dubbo 的实现, 在抛出 RejectedExecutionException 异常之前会记录日志, 并bump线程栈信息, 方便定位问题
                    Netty 的实现, 是创建一个新的线程来执行任务
                    ActiveMQ 的实现, 带超时等待(60s)尝试放入队列, 类似我们之前自定义的拒绝策略
                    PinPoint 的实现, 它使用了一个拒绝策略链, 会逐一尝试策略链中每种拒绝策略
                 */
                new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

                    }
                }
        );

        // 线程池运行方法
        poolRunMethod(pool);

        // 关闭线程池
        poolEnd(pool);
    }

    private static void poolEnd(ThreadPoolExecutor pool) throws InterruptedException {
        /**
         * 线程池状态变为 SHUTDOWN
         *  不会接收新任务
         *  已提交任务会执行完
         *  不会阻塞调用线程的执行
         */
        pool.shutdown();

        /**
         * 线程池状态变为 STOP
         *  不会接收新任务
         *  会将队列中的任务返回
         *  并用 interrupt 的方式中断正在执行的任务
         */
        pool.shutdownNow();

        // 不在 RUNNING 状态的线程池, 此方法就返回 true
        pool.isShutdown();

        // 线程池状态是否是 TERMINATED
        pool.isTerminated();

        // 调用 shutdown 后, 由于调用线程并不会等待所有任务运行结束, 因此如果它想在线程池 TERMINATED 后做些事情, 可以利用此方法等待
        pool.awaitTermination(1000, TimeUnit.MILLISECONDS);
    }

    private static void poolRunMethod(ThreadPoolExecutor pool) throws InterruptedException, ExecutionException, TimeoutException {
        // 执行任务
        pool.execute(() -> {
        });

        // 提交任务 task, 用返回值 Future 获得任务执行结果
        pool.submit(() -> {
        });

        // 提交 tasks 中所有任务
        pool.invokeAll(Collections.emptyList());

        // 提交 tasks 中所有任务, 带超时时间
        pool.invokeAll(Collections.emptyList(), 1, TimeUnit.MILLISECONDS);

        // 提交 tasks 中所有任务, 哪个任务先成功执行完毕, 返回此任务执行结果, 其他任务取消
        pool.invokeAny(Collections.emptyList());

        // 提交 tasks 中所有任务, 哪个任务先成功执行完毕, 返回此任务执行结果, 其他任务取消, 带超时时间
        pool.invokeAny(Collections.emptyList(), 1, TimeUnit.MILLISECONDS);
    }

}
